package com.shaw.study.springx.aop;

import com.shaw.study.springx.annotation.Transaction;
import com.shaw.study.springx.transaction.TransactionManager;

import javax.sql.DataSource;
import java.lang.reflect.*;
import java.lang.reflect.Proxy;

/**
 * Created by asus on 2018/5/10.
 */
public class TransactionAopProxy implements InvocationHandler{
    private Object target;

    private volatile Object prxoyObject;

    public TransactionAopProxy(Object target){
        this.target = target;
    }

    public Object getTarget(){
        return target;
    }


    public Object getProxy(){
        Class clazz = this.target.getClass();
        return Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), this);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        if (method.isAnnotationPresent(Transaction.class)) {
            Transaction transaction = method.getAnnotation(Transaction.class);
            TransactionManager transactionManager = TransactionManager.getInstances();
            transactionManager.start();
            try{
                Object returnObject = method.invoke(target,args);
                transactionManager.commit();
                return returnObject;
            }catch (Exception e){
                Class clazz = transaction.rollbackfor();
                if((clazz!=null&&(e.getClass()==clazz||clazz.isAssignableFrom(e.getClass())))||clazz==null){
                    transactionManager.rollback();
                }
                if(e.getClass()==InvocationTargetException.class){
                    InvocationTargetException ite = (InvocationTargetException)e;
                    throw ite.getTargetException();
                }
                throw e;
            }finally {
                transactionManager.close();
            }
        }

        return method.invoke(target,args);
    }
}
